from fastapi import HTTPException, status
from sqlalchemy.orm import Session
from auth import create_access_token, create_refresh_token, verify_refresh_token
from models import User, Role, Permission, UserRole, RolePermission
import bcrypt
from schemas import (
    UserCreate, UserUpdate, UserStatusUpdate, UserLogin, TokenOut,
    PasswordResetRequest, PasswordChange, TokenRefreshRequest,
    RoleCreate, RoleUpdate, PermissionCreate, PermissionUpdate
)

# 用户业务逻辑

def create_user(user: UserCreate, db: Session):
    if db.query(User).filter((User.username == user.username) | (User.email == user.email)).first():
        raise HTTPException(status_code=400, detail="用户名或邮箱已存在")
    salt = bcrypt.gensalt()
    password_hash = bcrypt.hashpw(user.password.encode('utf-8'), salt).decode('utf-8')
    db_user = User(
        username=user.username,
        email=user.email,
        password_hash=password_hash,
        salt=salt.decode('utf-8'),
        user_type=user.user_type,
        department=user.department
    )
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user

def get_user(user_id: int, db: Session):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    return user

def update_user(user_id: int, user: UserUpdate, db: Session):
    db_user = db.query(User).filter(User.id == user_id).first()
    if not db_user:
        raise HTTPException(status_code=404, detail="用户不存在")
    for k, v in user.dict(exclude_unset=True).items():
        setattr(db_user, k, v)
    db.commit()
    db.refresh(db_user)
    return db_user

def delete_user(user_id: int, db: Session):
    db_user = db.query(User).filter(User.id == user_id).first()
    if not db_user:
        raise HTTPException(status_code=404, detail="用户不存在")
    db.delete(db_user)
    db.commit()

def list_users(page: int, page_size: int, db: Session):
    query = db.query(User)
    total = query.count()
    items = query.offset((page-1)*page_size).limit(page_size).all()
    return {"total": total, "page": page, "page_size": page_size, "items": items}

def update_user_status(user_id: int, status: UserStatusUpdate, db: Session):
    db_user = db.query(User).filter(User.id == user_id).first()
    if not db_user:
        raise HTTPException(status_code=404, detail="用户不存在")
    # 使用Enum字段的python_type进行类型转换，确保兼容
    db_user.status = User.status.type.python_type(status.status)
    db.commit()
    db.refresh(db_user)
    return db_user

# 角色、权限等业务逻辑同理实现，可根据需要扩展 

def login_user(login: UserLogin, db: Session):
    user = db.query(User).filter(User.username == login.username).first()
    if not user or not bcrypt.checkpw(login.password.encode('utf-8'), user.password_hash.encode('utf-8')):
        raise HTTPException(status_code=401, detail="用户名或密码错误")
    access_token = create_access_token({"user_id": user.id, "username": user.username})
    refresh_token = create_refresh_token({"user_id": user.id, "username": user.username})
    return {"access_token": access_token, "refresh_token": refresh_token, "token_type": "bearer"}

def logout_user(token: str):
    # 如有token黑名单机制可实现，这里仅做接口占位
    return {"msg": "登出成功"}

def reset_password_request(req: PasswordResetRequest, db: Session):
    user = db.query(User).filter(User.email == req.email).first()
    if not user:
        raise HTTPException(status_code=404, detail="邮箱未注册")
    # 这里应发送邮件，实际开发中集成邮件服务
    return {"msg": "重置密码邮件已发送（模拟）"}

def change_password(user_id: int, pwd: PasswordChange, db: Session):
    user = db.query(User).filter(User.id == user_id).first()
    if not user or not bcrypt.checkpw(pwd.old_password.encode('utf-8'), user.password_hash.encode('utf-8')):
        raise HTTPException(status_code=401, detail="原密码错误")
    salt = bcrypt.gensalt()
    user.password_hash = bcrypt.hashpw(pwd.new_password.encode('utf-8'), salt).decode('utf-8')
    user.salt = salt.decode('utf-8')
    db.commit()
    return {"msg": "密码修改成功"}

def refresh_token_service(req: TokenRefreshRequest):
    payload = verify_refresh_token(req.refresh_token)
    access_token = create_access_token({"user_id": payload["user_id"], "username": payload["username"]})
    refresh_token = create_refresh_token({"user_id": payload["user_id"], "username": payload["username"]})
    return {"access_token": access_token, "refresh_token": refresh_token, "token_type": "bearer"} 

# 角色管理

def create_role(role: RoleCreate, db: Session):
    if db.query(Role).filter(Role.role_name == role.role_name).first():
        raise HTTPException(status_code=400, detail="角色名已存在")
    db_role = Role(role_name=role.role_name, description=role.description)
    db.add(db_role)
    db.commit()
    db.refresh(db_role)
    return db_role

def get_role(role_id: int, db: Session):
    role = db.query(Role).filter(Role.id == role_id).first()
    if not role:
        raise HTTPException(status_code=404, detail="角色不存在")
    return role

def update_role(role_id: int, role: RoleUpdate, db: Session):
    db_role = db.query(Role).filter(Role.id == role_id).first()
    if not db_role:
        raise HTTPException(status_code=404, detail="角色不存在")
    for k, v in role.dict(exclude_unset=True).items():
        setattr(db_role, k, v)
    db.commit()
    db.refresh(db_role)
    return db_role

def delete_role(role_id: int, db: Session):
    db_role = db.query(Role).filter(Role.id == role_id).first()
    if not db_role:
        raise HTTPException(status_code=404, detail="角色不存在")
    db.delete(db_role)
    db.commit()

def list_roles(page: int, page_size: int, db: Session):
    query = db.query(Role)
    total = query.count()
    items = query.offset((page-1)*page_size).limit(page_size).all()
    return {"total": total, "page": page, "page_size": page_size, "items": items}

def get_role_users(role_id: int, db: Session):
    users = db.query(User).join(UserRole, User.id == UserRole.user_id).filter(UserRole.role_id == role_id).all()
    return users

def assign_role_users(role_id: int, user_ids: list, db: Session):
    for user_id in user_ids:
        if not db.query(UserRole).filter_by(user_id=user_id, role_id=role_id).first():
            db.add(UserRole(user_id=user_id, role_id=role_id))
    db.commit()
    return {"msg": "分配成功"}

def remove_role_user(role_id: int, user_id: int, db: Session):
    ur = db.query(UserRole).filter_by(user_id=user_id, role_id=role_id).first()
    if ur:
        db.delete(ur)
        db.commit()
    return {"msg": "移除成功"}

# 权限管理

def create_permission(permission: PermissionCreate, db: Session):
    db_permission = Permission(**permission.dict())
    db.add(db_permission)
    db.commit()
    db.refresh(db_permission)
    return db_permission

def get_permission(permission_id: int, db: Session):
    permission = db.query(Permission).filter(Permission.id == permission_id).first()
    if not permission:
        raise HTTPException(status_code=404, detail="权限不存在")
    return permission

def update_permission(permission_id: int, permission: PermissionUpdate, db: Session):
    db_permission = db.query(Permission).filter(Permission.id == permission_id).first()
    if not db_permission:
        raise HTTPException(status_code=404, detail="权限不存在")
    for k, v in permission.dict(exclude_unset=True).items():
        setattr(db_permission, k, v)
    db.commit()
    db.refresh(db_permission)
    return db_permission

def delete_permission(permission_id: int, db: Session):
    db_permission = db.query(Permission).filter(Permission.id == permission_id).first()
    if not db_permission:
        raise HTTPException(status_code=404, detail="权限不存在")
    db.delete(db_permission)
    db.commit()

def list_permissions(page: int, page_size: int, db: Session):
    query = db.query(Permission)
    total = query.count()
    items = query.offset((page-1)*page_size).limit(page_size).all()
    return {"total": total, "page": page, "page_size": page_size, "items": items}

def get_permission_tree(db: Session):
    # 简单树形结构，按resource分组
    permissions = db.query(Permission).all()
    tree = {}
    for p in permissions:
        tree.setdefault(p.resource, []).append({"id": p.id, "action": p.action, "attribute_condition": p.attribute_condition})
    return tree

def assign_permission_roles(permission_id: int, role_ids: list, db: Session):
    for role_id in role_ids:
        if not db.query(RolePermission).filter_by(role_id=role_id, permission_id=permission_id).first():
            db.add(RolePermission(role_id=role_id, permission_id=permission_id))
    db.commit()
    return {"msg": "分配成功"}

def remove_permission_role(permission_id: int, role_id: int, db: Session):
    rp = db.query(RolePermission).filter_by(role_id=role_id, permission_id=permission_id).first()
    if rp:
        db.delete(rp)
        db.commit()
    return {"msg": "移除成功"} 